home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 4 / Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso / Development / General / DR1.#1 PowerPlant ƒ / LPrintout.cp < prev    next >
Text File  |  1994-02-10  |  12KB  |  445 lines

  1. // ===========================================================================
  2. //    LPrintout.cp                     ©1993 Metrowerks Inc. All rights reserved.
  3. // ===========================================================================
  4. //
  5. //    A View for printing
  6. //
  7. //    A Printout object is top level container of a view hierarchy that is
  8. //    being printed. It deals with the Mac Print Manager and coordinates
  9. //    its subpanes during the printing process.
  10. //
  11. //    To print, you must create a Printout object in which you install all
  12. //    the Panes that you want to print. Usually, your Printout has the
  13. //    dimensions of the paper size (as displayed in the Page Setup dialog).
  14. //    Then, the location of a Pane in the Printout is the same as the location
  15. //    on the Paper where the Pane will print.
  16. //
  17. //    To print a Pane that is inside a Window, you should use a LPlaceHolder
  18. //    view in the Printout to specify the size and location of the Pane when
  19. //    it prints. You then install the Pane inside the PlaceHolder. When
  20. //    printing completes, the PlaceHolder returns the Pane to its original
  21. //    place in the Window.
  22. //
  23. //    +++ Still under light construction
  24.  
  25. #include "LPrintout.h"
  26. #include "UPrinting.h"
  27. #include "LListIterator.h"
  28. #include "LStream.h"
  29. #include "LCommander.h"
  30. #include "UReanimator.h"
  31.  
  32. #include <GestaltEqu.h>
  33.  
  34.  
  35. // ---------------------------------------------------------------------------
  36. //        • CreatePrintout [static]
  37. // ---------------------------------------------------------------------------
  38. //    Return a new Printout object (and its SubPanes) from the data in
  39. //    a 'PObj' resource
  40.  
  41. LPrintout*
  42. LPrintout::CreatePrintout(
  43.     ResIDT        inPrintoutID)
  44. {
  45.     LCommander::SetDefaultCommander(nil);
  46.     LPrintout    *thePrintout =
  47.             (LPrintout*) UReanimator::ReadObjects('PObj', inPrintoutID);
  48.     thePrintout->FinishCreate();
  49.     
  50.     return thePrintout;
  51. }
  52.  
  53.  
  54. // ---------------------------------------------------------------------------
  55. //        • CreatePrintoutStream [static]
  56. // ---------------------------------------------------------------------------
  57. //    Return a new Printout object initialized using data from a Stream
  58.  
  59. LPrintout*
  60. LPrintout::CreatePrintoutStream(
  61.     LStream    *inStream)
  62. {
  63.     DataIDT        dataID;
  64.     inStream->ReadData(&dataID, sizeof(DataIDT));
  65.     SignalIf_(dataID != 'PrtO');
  66.     
  67.     return (new LPrintout(inStream));
  68. }
  69.  
  70.  
  71. // ---------------------------------------------------------------------------
  72. //        • LPrintout
  73. // ---------------------------------------------------------------------------
  74. //    Default Constructor
  75.  
  76. LPrintout::LPrintout()
  77. {
  78.     InitPrintout();
  79. }
  80.  
  81.  
  82. // ---------------------------------------------------------------------------
  83. //        • LPrintout(THPrint)
  84. // ---------------------------------------------------------------------------
  85. //    Construct a Printout from an existing PrintRecord
  86.  
  87. LPrintout::LPrintout(
  88.     THPrint    inPrintRecordH)
  89. {
  90.     InitPrintout();
  91.     SetPrintRecord(inPrintRecordH);
  92. }
  93.  
  94.  
  95. // ---------------------------------------------------------------------------
  96. //        • LPrintout
  97. // ---------------------------------------------------------------------------
  98. //    Construct a Printout from the data in a Stream
  99.  
  100. LPrintout::LPrintout(
  101.     LStream    *inStream)
  102. {
  103.     InitPrintout();
  104.     inStream->ReadData(&mAttributes, sizeof(Uint32));
  105.     SetDefaultView(this);
  106. }
  107.  
  108.  
  109. // ---------------------------------------------------------------------------
  110. //        • InitPrintout
  111. // ---------------------------------------------------------------------------
  112. //    Initialize data members to default values
  113.  
  114. void
  115. LPrintout::InitPrintout()
  116. {
  117.     mAttributes = 0;
  118.     mPrinterPort = nil;
  119.     mHorizPanelCount = 1;
  120.     mVertPanelCount = 1;
  121.     
  122.     SetPrintRecord(UPrinting::GetDefaultPrintRecord());
  123.     
  124.                                     // Create an empty, invisible window
  125.                                     //   for installing Toolbox Controls
  126.     Rect    bounds = {0, 0, 0, 0};
  127.     Int32        qdVersion;
  128.     OSErr    err = Gestalt(gestaltQuickdrawVersion, &qdVersion);
  129.     if ( (err != noErr)  ||  (qdVersion == gestaltOriginalQD) ) {
  130.         mWindowPort = NewWindow(nil, &bounds, "\p", false, documentProc,
  131.                             nil, false, 0);
  132.     } else {
  133.         mWindowPort = NewCWindow(nil, &bounds, "\p", false, documentProc,
  134.                             nil, false, 0);
  135.     }
  136.     SetPort(mWindowPort);
  137.     OutOfFocus(nil);
  138.     
  139.     SuperActivate();                // A Printout is active and visible
  140.     SuperShow();
  141. }
  142.  
  143.  
  144. // ---------------------------------------------------------------------------
  145. //        • ~LPrintout
  146. // ---------------------------------------------------------------------------
  147. //    Destructor
  148.  
  149. LPrintout::~LPrintout()
  150. {
  151.     DeleteAllSubPanes();
  152.  
  153.     if (mWindowPort != nil) {
  154.         DisposeWindow(mWindowPort);
  155.     }
  156. }
  157.  
  158.  
  159. THPrint
  160. LPrintout::GetPrintRecord()
  161. {
  162.     return    mPrintRecordH;
  163. }
  164.  
  165.  
  166. // ---------------------------------------------------------------------------
  167. //        • SetPrintRecord
  168. // ---------------------------------------------------------------------------
  169. //    Set the Toolbox PrintRecord for a Printout
  170.  
  171. void
  172. LPrintout::SetPrintRecord(
  173.     THPrint    inPrintRecordH)
  174. {
  175.     mPrintRecordH = inPrintRecordH;
  176.     UPrinting::ValidatePrintRecord(inPrintRecordH);
  177.     
  178.         // Size and coordinates system of a Printout depend on the Page
  179.         // and Paper rectangles of the PrintRecord. The Print Manager sets
  180.         // the port rectangle of the Printer Port to the Page rectangle.
  181.         //
  182.         // The Page rectangle is usually smaller than the Paper rectangle
  183.         // since most printers have mechanical limitations which prevent
  184.         // them from printing to the very edge of the paper.
  185.         //
  186.         // For Printouts, it seems more natural to have (0,0) be the top left
  187.         // of the Paper rectangle, so that coordinates are the absolute
  188.         // location on the paper. This simplifies setting margins and
  189.         // otherwise placing Panes for printing.
  190.     
  191.     Rect    paperRect = (**inPrintRecordH).rPaper;
  192.     
  193.         // Printout Frame and Image match the Paper Rectangle
  194.     
  195.     ResizeFrameTo(paperRect.right - paperRect.left,
  196.                     paperRect.bottom - paperRect.top, false);
  197.     ResizeImageTo(paperRect.right - paperRect.left,
  198.                     paperRect.bottom - paperRect.top, false);
  199.     MoveBy(paperRect.left, paperRect.top, false);
  200. }
  201.  
  202.  
  203. // ---------------------------------------------------------------------------
  204. //        • HasAttribute
  205. // ---------------------------------------------------------------------------
  206. //    Return whether a Printout has the specified attribute
  207.  
  208. Boolean
  209. LPrintout::HasAttribute(
  210.     EPrintAttr    inAttribute)
  211. {
  212.     return ((mAttributes & inAttribute) != 0);
  213. }
  214.  
  215.  
  216. void
  217. LPrintout::DoPrintJob()
  218. {
  219.     PanelSpec    firstPanel;
  220.     PanelSpec    lastPanel;
  221.     Uint16        copyCount;
  222.     GetPrintJobSpecs(firstPanel, lastPanel, copyCount);
  223.     PrintPanelRange(firstPanel, lastPanel, copyCount);
  224. }
  225.  
  226.  
  227. void
  228. LPrintout::PrintPanelRange(
  229.     const PanelSpec    &inFirstPanel,
  230.     const PanelSpec    &inLastPanel,
  231.     Uint16            inCopyCount)
  232. {
  233.     if (UPrinting::OpenPrinter()) {
  234.     
  235.             // +++ Show print status dialog
  236.  
  237.         PrintCopiesOfPages(inFirstPanel, inLastPanel, inCopyCount);
  238.     }
  239.     
  240.     Int16    printError = PrError();
  241.     UPrinting::ClosePrinter();
  242.     
  243.     if (printError) {
  244.             // +++ Post error message
  245.     }
  246.     
  247.             // +++ Remove print status dialog
  248. }
  249.  
  250.  
  251. // ---------------------------------------------------------------------------
  252. //        • CountPanels
  253. // ---------------------------------------------------------------------------
  254. //    Count the number of Panels in a Printout
  255.  
  256. void
  257. LPrintout::CountPanels(
  258.     Uint32    &outHorizPanels,
  259.     Uint32    &outVertPanels)
  260. {
  261.         // The number of Panels in a Printout is the maximum number
  262.         // (both horizonal and vertical) of Panels in its SubPanes
  263.  
  264.     Uint32    maxHorizPanels = 1;
  265.     Uint32    maxVertPanels = 1;
  266.     
  267.     LListIterator    iterator(GetSubPanes(), iterate_FromStart);
  268.     LPane    *subPane;
  269.     while (iterator.Next(subPane)) {
  270.         Uint32    subHorizPanels;
  271.         Uint32    subVertPanels;
  272.         subPane->CountPanels(subHorizPanels, subVertPanels);
  273.         if (subHorizPanels > maxHorizPanels) {
  274.             maxHorizPanels = subHorizPanels;
  275.         }
  276.         if (subVertPanels > maxVertPanels) {
  277.             maxVertPanels = subVertPanels;
  278.         }
  279.     }
  280.                                     // Save counts in member variables
  281.                                     //   and set output parameters
  282.     mHorizPanelCount = outHorizPanels = maxHorizPanels;
  283.     mVertPanelCount = outVertPanels = maxVertPanels;
  284. }
  285.  
  286.  
  287. // ---------------------------------------------------------------------------
  288. //        • PageToPanel
  289. // ---------------------------------------------------------------------------
  290. //    Fill in PanelSpec for a given page number
  291.  
  292. void
  293. LPrintout::PageToPanel(
  294.     Uint32        inPageNumber,
  295.     PanelSpec    &outPanel)
  296. {
  297.     outPanel.pageNumber = inPageNumber;
  298.  
  299.     Boolean    numberDown = true;        // +++ Make a Printout attribute
  300.     
  301.     if (numberDown) {
  302.         outPanel.horizIndex = ((inPageNumber - 1) / mVertPanelCount) + 1;
  303.         outPanel.vertIndex = ((inPageNumber - 1) % mVertPanelCount) + 1;
  304.         
  305.     } else {
  306.         outPanel.horizIndex = ((inPageNumber - 1) % mHorizPanelCount) + 1;
  307.         outPanel.vertIndex = ((inPageNumber - 1) / mHorizPanelCount) + 1;
  308.     }
  309. }
  310.  
  311.  
  312. void
  313. LPrintout::GetPrintJobSpecs(
  314.     PanelSpec    &outFirstPanel,
  315.     PanelSpec    &outLastPanel,
  316.     Uint16        &outCopyCount)
  317. {
  318.     THPrint    printRecordH = GetPrintRecord();
  319.     
  320.                                 // Get info from PrintRecord
  321.     Int16    firstPage = (**printRecordH).prJob.iFstPage;
  322.     Int16    lastPage = (**printRecordH).prJob.iLstPage;
  323.     outCopyCount = (**printRecordH).prJob.iCopies;
  324.     
  325.         // The Print Manager doesn't care about our page numbers. It
  326.         // counts the number of calls to PrOpenPage. So setting the
  327.         // page range to 1 to 9999 will print all pages that we draw.  
  328.     
  329.     (**printRecordH).prJob.iFstPage = 1;
  330.     (**printRecordH).prJob.iLstPage = 9999;
  331.  
  332.         // Enforce bounds on page range. Last page can't be greater
  333.         // than number of pages in Printout, and first page can't
  334.         // be greater than the last page.
  335.     
  336.     Uint32    horizPanelCount;
  337.     Uint32    vertPanelCount;
  338.     CountPanels(horizPanelCount, vertPanelCount);
  339.     Uint32    pageCount = horizPanelCount * vertPanelCount;
  340.  
  341.     if (lastPage > pageCount) {
  342.         lastPage = pageCount;
  343.     }
  344.     
  345.     if (firstPage > lastPage) {
  346.         firstPage = lastPage;
  347.     }
  348.     
  349.     PageToPanel(firstPage, outFirstPanel);
  350.     PageToPanel(lastPage, outLastPanel);
  351. }
  352.  
  353.  
  354. void
  355. LPrintout::PrintCopiesOfPages(
  356.     const PanelSpec    &inFirstPanel,
  357.     const PanelSpec    &inLastPanel,
  358.     Uint16            inCopyCount)
  359. {
  360.     THPrint    printRecordH = GetPrintRecord();
  361.     Int16    printMgrResFile = CurResFile();
  362.  
  363.     for (Uint16 copy = 1; copy <= inCopyCount; copy++) {
  364.  
  365.         // +++ Install pIdle proc
  366.  
  367.         UseResFile(printMgrResFile);
  368.  
  369.         mPrinterPort = ::PrOpenDoc(printRecordH, nil , nil);
  370.         OutOfFocus(nil);            // Printer is the current port
  371.         
  372.         PanelSpec    thePanel = inFirstPanel;
  373.         while (thePanel.pageNumber <= inLastPanel.pageNumber &&
  374.                 PrError() == noErr) {
  375.                 
  376.             ::PrOpenPage(mPrinterPort, nil);
  377.  
  378.             if (PrError() == noErr) {
  379.                 PrintPanel(thePanel, nil);
  380.             }
  381.  
  382.             :: PrClosePage(mPrinterPort);
  383.             
  384.             PageToPanel(++thePanel.pageNumber, thePanel);
  385.         }
  386.  
  387.         ::PrCloseDoc(mPrinterPort);
  388.         mPrinterPort = nil;
  389.     }
  390.     OutOfFocus(nil);                // Printer port is gone
  391.  
  392.     if (((**printRecordH).prJob.bJDocLoop == bSpoolLoop) && (PrError() == noErr)) {
  393.         TPrStatus    printStatus;
  394.         ::PrPicFile(printRecordH, nil, nil, nil, &printStatus);
  395.     }
  396. }
  397.  
  398.  
  399. void
  400. LPrintout::PrintPanel(
  401.     const PanelSpec    &inPanel,
  402.     RgnHandle    inSuperPrintRgnH)
  403. {
  404.     FocusDraw();
  405.     PrintPanelSelf(inPanel);        // Print this Printout
  406.     
  407.                                     // Print SubPanes
  408.     LListIterator    iterator(GetSubPanes(), iterate_FromStart);
  409.     LPane    *subPane;
  410.     while (iterator.Next(subPane)) {
  411.         subPane->PrintPanel(inPanel, inSuperPrintRgnH);
  412.     }
  413. }
  414.  
  415.  
  416. // ---------------------------------------------------------------------------
  417. //        • GetMacPort
  418. // ---------------------------------------------------------------------------
  419. //    Return the GrafPort associated with a Printout
  420.  
  421. GrafPtr
  422. LPrintout::GetMacPort() const
  423. {
  424.     return (GrafPtr) mPrinterPort;
  425. }
  426.  
  427.  
  428. // ---------------------------------------------------------------------------
  429. //        • EstablishPort
  430. // ---------------------------------------------------------------------------
  431. //    Make Printout the current Port
  432.  
  433. void
  434. LPrintout::EstablishPort()
  435. {
  436.         // A Printer Port only exists during the print loop. At other
  437.         // times, we have to use the window port. 
  438.     
  439.     GrafPtr    printoutPort = (GrafPtr) mPrinterPort;
  440.     if (mPrinterPort == nil) {
  441.         printoutPort = mWindowPort;
  442.     }
  443.     SetPort(printoutPort);
  444. }
  445.